LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;

ENTITY CompVGAcontroller IS
	GENERIC(
		h_pulse 	:	INTEGER := 208;    	--horiztonal sync pulse width in pixels
		h_bp	 	:	INTEGER := 336;		--horiztonal back porch width in pixels
		h_pixels	:	INTEGER := 1920;		--horiztonal display width in pixels
		h_fp	 	:	INTEGER := 128;		--horiztonal front porch width in pixels
		h_pol		:	STD_LOGIC := '0';		--horizontal sync pulse polarity (1 = positive, 0 = negative)
		v_pulse 	:	INTEGER := 3;			--vertical sync pulse width in rows
		v_bp	 	:	INTEGER := 38;			--vertical back porch width in rows
		v_pixels	:	INTEGER := 1200;		--vertical display width in rows
		v_fp	 	:	INTEGER := 1;			--vertical front porch width in rows
		v_pol		:	STD_LOGIC := '1');	--vertical sync pulse polarity (1 = positive, 0 = negative)
	PORT(
		GReset		:	IN		STD_LOGIC;	--Глобальный сброс
	   pixel_clk	:	IN		STD_LOGIC;	--pixel clock at frequency of VGA mode being used
		h_sync		:	OUT	STD_LOGIC;	--horiztonal sync pulse
		v_sync		:	OUT	STD_LOGIC;	--vertical sync pulse
		DisplayEn		:	OUT	STD_LOGIC;	--display enable ('1' = display time, '0' = blanking time)
		column		:	OUT	std_logic_vector(31 downto 0);		--horizontal pixel coordinate
		row			:	OUT	std_logic_vector(31 downto 0);		--vertical pixel coordinate
		count_pixel :  OUT   std_logic_vector(31 downto 0);    --counter pixels
		n_blank		:	OUT	STD_LOGIC;	--direct blacking output to DAC
		n_sync		:	OUT	STD_LOGIC; --sync-on-green output to DAC
		Frame1 : OUT std_logic;
      Frame2 : OUT std_logic
	); 
END CompVGAcontroller;

ARCHITECTURE ArchVGAcontroller OF CompVGAcontroller IS
	CONSTANT	h_period	:	INTEGER := h_pulse + h_bp + h_pixels + h_fp;  --total number of pixel clocks in a row
	CONSTANT	v_period	:	INTEGER := v_pulse + v_bp + v_pixels + v_fp;  --total number of rows in column
	
	SIGNAL sigDisplayEn : STD_LOGIC := '0';
	SIGNAL sigFrame1    : STD_LOGIC := '0';
   SIGNAL sigFrame2    : STD_LOGIC := '0';
BEGIN

	n_blank <= '1';  --no direct blanking
	n_sync <= '0';   --no sync on green
	
	PROCESS(GReset, pixel_clk)
		VARIABLE h_count	:	INTEGER RANGE 0 TO h_period - 1 := 0;  --horizontal counter (counts the columns)
		VARIABLE v_count	:	INTEGER RANGE 0 TO v_period - 1 := 0;  --vertical counter (counts the rows)
		VARIABLE vCountPixels :	INTEGER RANGE 0 TO (h_period - 1)*(v_period - 1) := 0;  --counter pixel
	BEGIN
	
		IF(GReset = '1') THEN		--reset asserted
			h_count := 0;				--reset horizontal counter
			v_count := 0;				--reset vertical counter
			vCountPixels := 0;      --reser counter pixels
			h_sync <= NOT h_pol;		--deassert horizontal sync
			v_sync <= NOT v_pol;		--deassert vertical sync
			sigDisplayEn <= '0';			--disable display
			column <= (OTHERS => '0');				--reset column pixel coordinate
			row <= (OTHERS => '0');					--reset row pixel coordinate
			
		ELSIF(pixel_clk'EVENT AND pixel_clk = '1') THEN

			--counters
			IF(h_count < h_period - 1) THEN		--horizontal counter (pixels)
				h_count := h_count + 1;
				if(h_count>400-160 and h_count<401+160) then
				 vCountPixels := vCountPixels + 1;
				end if;
			ELSE
				h_count := 0;
				--vCountPixels := 0;
				IF(v_count < v_period - 1) THEN	--veritcal counter (rows)
					v_count := v_count + 1;
					if(v_count>300-120 and v_count<301+120) then
				    else
					  vCountPixels := 0;
				   end if;
				ELSE
					v_count := 0;
					vCountPixels := 0;
				END IF;
			END IF;

			--horizontal sync signal
			IF(h_count < h_pixels + h_fp OR h_count > h_pixels + h_fp + h_pulse) THEN
				h_sync <= NOT h_pol;		--deassert horiztonal sync pulse
			ELSE
				h_sync <= h_pol;			--assert horiztonal sync pulse
			END IF;
			
			--vertical sync signal
			IF(v_count < v_pixels + v_fp OR v_count > v_pixels + v_fp + v_pulse) THEN
				v_sync <= NOT v_pol;		--deassert vertical sync pulse
			ELSE
				v_sync <= v_pol;			--assert vertical sync pulse
			END IF;
			
			--set pixel coordinates
			IF(h_count < h_pixels) THEN  	--horiztonal display time
				column <= conv_std_logic_vector(h_count,32);			--set horiztonal pixel coordinate
			END IF;
			IF(v_count < v_pixels) THEN	--vertical display time
				row <= conv_std_logic_vector(v_count,32);				--set vertical pixel coordinate
			END IF;
			count_pixel <= conv_std_logic_vector(vCountPixels,32);

			--set display enable output
			IF(h_count < h_pixels AND v_count < v_pixels) THEN  	--display time
				sigDisplayEn <= '1';											 	--enable display
			ELSE																	--blanking time
				sigDisplayEn <= '0';												--disable display
			END IF;

		END IF;
	END PROCESS;

DisplayEn <= sigDisplayEn;
	
procFrame : PROCESS (GReset, sigDisplayEn)
 VARIABLE vCount : STD_LOGIC;
BEGIN
    IF(sigDisplayEn'event AND sigDisplayEn = '0') THEN
        IF (GReset = '1') THEN
            vCount := '0';
            sigFrame1 <= '1';
            sigFrame2 <= '0';
        ELSIF (vCount = '0') THEN
            sigFrame1 <= '1';
            sigFrame2 <= '0';
            vCount := '1';
        ELSIF (vCount = '1') THEN
            sigFrame1 <= '0';
           sigFrame2 <= '1';
           vCount := '0';
        END IF;
    END IF;
END PROCESS procFrame;
Frame1 <= sigFrame1;
Frame2 <= sigFrame2;

END ArchVGAcontroller;